using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using bitzhuwei.Compiler;

namespace bitzhuwei.AnsiCFormat {
    /// <summary>
    /// Correspond to the Vn node compound_statement in the grammar(AnsiC).
    /// </summary>
    internal partial class Vncompound_statement : Vnstatement {
        // [181]=compound_statement : '{' '}' ;
        // [182]=compound_statement : '{' statement_list '}' ;
        // [183]=compound_statement : '{' declaration_list '}' ;
        // [184]=compound_statement : '{' declaration_list statement_list '}' ;

        public Vncompound_statement(Token r3, Vndeclaration_list? r2, Vnstatement_list? r1, Token r0) {
            this.r3 = r3;
            this.r2 = r2;
            this.r1 = r1;
            this.r0 = r0;
            this._scope = new TokenRange(r3, r0);
        }

        private readonly Token r3;
        private readonly Vndeclaration_list? r2;
        private readonly Vnstatement_list? r1;
        private readonly Token r0;
        private readonly TokenRange _scope;

        public override TokenRange Scope => _scope;

        public override void Format(TextWriter writer, FormatContext context) {
            throw new NotImplementedException();
        }

        public override void FullFormat(BlankConfig preConfig, TextWriter writer, FormatContext context) {
            { // print {
                context.PrintBlanksAnd(this.r3, preConfig, writer);
            }
            var forceNewline = this.r0.start.line > this.r3.end.line;
            context.IncreaseTab();
            if (this.r2 != null && this.r1 != null) {
                var config = new BlankConfig(inlineBlank: 1, forceNewline: false);
                // comment after { need not to print in next line
                context.PrintCommentsBetween(this.r3, this.r2, config, writer);
                var config2 = config;
                config2.forceNewline = forceNewline;
                // statements need to print in next line
                context.PrintBlanksAnd(r2, config2, writer);
                // print comments between statement list and }
                context.PrintCommentsBetween(this.r2, this.r1, config, writer);
                context.PrintBlanksAnd(r1, config, writer);
                context.PrintCommentsBetween(this.r1, this.r0, config, writer);
            }
            else if (this.r2 != null) {
                var config = new BlankConfig(inlineBlank: 1, forceNewline: false);
                // comment after { need not to print in next line
                context.PrintCommentsBetween(this.r3, this.r2, config, writer);
                var config2 = config;
                config2.forceNewline = forceNewline;
                // statements need to print in next line
                context.PrintBlanksAnd(r2, config2, writer);
                // print comments between statement list and }
                context.PrintCommentsBetween(this.r2, this.r0, config, writer);
            }
            else if (this.r1 != null) {
                var config = new BlankConfig(inlineBlank: 1, forceNewline: false);
                // comment after { need not to print in next line
                context.PrintCommentsBetween(this.r3, this.r1, config, writer);
                var config2 = config;
                config2.forceNewline = forceNewline;
                // statements need to print in next line
                context.PrintBlanksAnd(r1, config2, writer);
                // print comments between statement list and }
                context.PrintCommentsBetween(this.r1, this.r0, config, writer);
            }
            else {
                var config = new BlankConfig(inlineBlank: 1, forceNewline: false);
                // comment after { need not to print in next line
                context.PrintCommentsBetween(this.r3, this.r0, config, writer);
            }
            context.DecreaseTab();
            { // print }
                var config = new BlankConfig(inlineBlank: 1, forceNewline);
                context.PrintBlanksAnd(this.r0, config, writer);
            }
        }

        public override IEnumerable<string> YieldTokens(TextWriter writer, FormatContext context) {
            throw new NotImplementedException();
        }

    }
}
